# coding=utf-8
# Implements of a simple knn algorithm
from numpy import *
import operator


def create_data_set():
    group = array([[1.0, 1.1], [1.0, 1.0], [0, 0], [0, 0.1]])
    labels = ['A', 'A', 'B', 'B']
    return group, labels


def classify0(x, data_set, labels, k):
    """
    Use k-Nearest-Neighbor method to categorize the data set.
    When pass a x, compute the distance from x to all data set.
    Select the nearest k data. Return the type of input x based
    on the categories of these nearest k data.
    :param x: the data need to determine the category.
    :param data_set: the training data set
    :param labels: the training data set's category
    :param k: k-param
    :return: the inX's type.
    """
    # calculate the distance
    data_set_size = data_set.shape[0]  # line count.
    diff_mat = tile(x, (data_set_size, 1)) - data_set  # the difference
    sq_diff_mat = diff_mat**2  # square difference
    sq_distance = sq_diff_mat.sum(axis=1)
    distances = sq_distance**0.5
    sorted_distances = distances.argsort()

    # select k data from front distance
    class_count = {}
    for i in range(k):
        vote_label_index = labels[sorted_distances[i]]
        class_count[vote_label_index] = class_count.get(vote_label_index, 0) + 1

    sorted_class_count = sorted(class_count.iteritems(), key=operator.itemgetter(1),
                                reverse=True)
    return sorted_class_count[0][0]


def auto_norm(data_set):
    min_vals = data_set.min(0)
    max_vals = data_set.max(0)
    ranges = max_vals - min_vals
    m = data_set.shape[0]
    normDataSet = data_set - tile(min_vals, (m, 1))
    normDataSet = normDataSet / tile(ranges, (m, 1))
    return normDataSet, ranges, min_vals
